package io.renren.common.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.nio.charset.StandardCharsets;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.*;

/**
 * @author yewenze
 */
@Slf4j
@Component
public class HttpUtil2 {

	private HttpUtil2() {
	}

	public String doGet(String url, Map<String, String> header, Map<String, String> params) throws Exception {
		URIBuilder uriBuilder = new URIBuilder(url);
		for (String key : params.keySet()) {
			uriBuilder.addParameter(key, params.get(key));
		}
		HttpClient httpClient;
		HttpGet postMethod;
		HttpResponse response;
		String reponseContent;
		httpClient = HttpClients.createDefault();
		postMethod = new HttpGet(uriBuilder.build());
		if(!CollectionUtils.isEmpty(header)){
			for (String key : header.keySet()) {
				postMethod.addHeader(key, header.get(key));
			}
		}
		response = httpClient.execute(postMethod);
		HttpEntity httpEntity = response.getEntity();
		reponseContent = EntityUtils.toString(httpEntity);
		EntityUtils.consume(httpEntity);
		return reponseContent;
	}

	public static String getBase64FromInputStream(InputStream in) {
        // 将图片文件转化为字节数组字符串，并对其进行Base64编码处理
        byte[] data = null;
        // 读取图片字节数组
        try {
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = in.read(buff, 0, 100)) > 0) {
                swapStream.write(buff, 0, rc);
            }
            data = swapStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return new String(Base64.encodeBase64(data));
    }

	// application/json格式请求
	public static String doHeaderPost(String url, String jsonParam, Map<String, String> paramHeader) {
		// 声明返回结果
		String result = "";
		// 开始请求API接口时间
		long startTime = System.currentTimeMillis();
		// 请求API接口的响应时间
		long endTime = 0L;
		HttpEntity httpEntity = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(3000000).setConnectionRequestTimeout(3000000)
				.setSocketTimeout(300000).build();
		try {
			// 设置请求头和报文
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			Header header = new BasicHeader("Accept-Encoding", "utf-8");
			for (String key : paramHeader.keySet()) {
				httpPost.setHeader(key, paramHeader.get(key));
			}
			httpPost.setHeader("Content-Type", "application/json");
			httpPost.setHeader(header);
			// 设置报文和通讯格式
			if (jsonParam != null) {
				StringEntity stringEntity = new StringEntity(jsonParam, "UTF-8");
				stringEntity.setContentEncoding("UTF-8");
				httpPost.setEntity(stringEntity);
			}

			// 执行发送，获取相应结果
			httpResponse = httpClient.execute(httpPost);
			httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity);
		} catch (Exception e) {
			log.error("请求http接口失败", e);
//			throw new ServiceException(406, "请求http接口失败");

		} finally {
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				log.error("HttpUtil.doPost finally EntityUtils.consume:", e);
			}
		}
		// 请求接口的响应时间
		endTime = System.currentTimeMillis();
		log.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
		return result;
	}

	public static String doPost(String url, String jsonParam) {
		// 声明返回结果
		String result = "";
		// 开始请求API接口时间
		long startTime = System.currentTimeMillis();
		// 请求API接口的响应时间
		long endTime = 0L;
		HttpEntity httpEntity = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000)
				.setSocketTimeout(5000).build();
		try {
			// 设置请求头和报文
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			Header header = new BasicHeader("Accept-Encoding", null);
			httpPost.setHeader(header);
			// 设置报文和通讯格式
			if (jsonParam != null) {
				StringEntity stringEntity = new StringEntity(jsonParam, "UTF-8");
				stringEntity.setContentEncoding("UTF-8");
				stringEntity.setContentType("application/x-www-form-urlencoded");
				httpPost.setEntity(stringEntity);
			}

			// 执行发送，获取相应结果
			httpResponse = httpClient.execute(httpPost);
			httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity);
		} catch (Exception e) {
			log.error("请求http接口失败", e);
//			throw new ServiceException(406, "请求http接口失败");

		} finally {
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				log.error("HttpUtil.doPost finally EntityUtils.consume:", e);
			}
		}
		// 请求接口的响应时间
		//endTime = System.currentTimeMillis();
		//log.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
		return result;
	}

	public static String doPost2(String url, String jsonParam) {
//		log.info("请求参数{},url{}",jsonParam,url);
		// 声明返回结果
		String result = "";
		// 开始请求API接口时间
		long startTime = System.currentTimeMillis();
		// 请求API接口的响应时间
		long endTime = 0L;
		HttpEntity httpEntity = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000)
				.setSocketTimeout(5000).build();
		try {
			// 设置请求头和报文
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			httpPost.setHeader("Content-Type","application/json;charset=utf-8");
			// 设置报文和通讯格式
			if (jsonParam != null) {
				StringEntity stringEntity = new StringEntity(jsonParam, "UTF-8");
				stringEntity.setContentEncoding("UTF-8");
				stringEntity.setContentType("application/json;charset=utf-8");
				httpPost.setEntity(stringEntity);
			}

			// 执行发送，获取相应结果
			httpResponse = httpClient.execute(httpPost);
			httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity);
		} catch (Exception e) {
			log.error("请求http接口失败", e);
//			throw new ServiceException(406, "请求http接口失败");

		} finally {
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				log.error("HttpUtil.doPost finally EntityUtils.consume:", e);
			}
		}
		// 请求接口的响应时间
		endTime = System.currentTimeMillis();
//		log.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
		return result;
	}

	public static JSONObject doHeaderPostW(String url, Map<String, String> parms, Map<String, String> paramHeader) {
		HttpPost httpPost = new HttpPost(url);
		ArrayList<BasicNameValuePair> list = new ArrayList<>();
		parms.forEach((key, value) -> list.add(new BasicNameValuePair(key, value)));
		CloseableHttpClient httpClient = HttpClients.createDefault();
		try {
			for (String key : paramHeader.keySet()) {
				httpPost.setHeader(key, paramHeader.get(key));
			}
			if (Objects.nonNull(parms) && parms.size() > 0) {
				httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8"));
			}
			InputStream content = httpPost.getEntity().getContent();
			InputStreamReader inputStreamReader = new InputStreamReader(content, "UTF-8");
			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
			String readLine = bufferedReader.readLine();
//            System.out.println("readLine===================================" + readLine);
			HttpResponse response = httpClient.execute(httpPost);
			HttpEntity entity = response.getEntity();
			JSONObject jsonObject = JSON.parseObject(EntityUtils.toString(entity, "UTF-8"));
			return jsonObject;
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (Objects.nonNull(httpClient)) {
				try {
					httpClient.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		return null;
	}

	public static String doPostForSap(String url, String jsonParam) {
		// 声明返回结果
		String result = "";
		// 开始请求API接口时间
		long startTime = System.currentTimeMillis();
		// 请求API接口的响应时间
		long endTime = 0L;
		HttpEntity httpEntity = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(10000).setConnectionRequestTimeout(5000)
				.setSocketTimeout(10000).build();
		try {
			// 设置请求头和报文
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			Header header = new BasicHeader("Accept-Encoding", null);
			httpPost.setHeader(header);
			// 设置报文和通讯格式
			StringEntity stringEntity = new StringEntity(jsonParam, "UTF-8");
			stringEntity.setContentEncoding("UTF-8");
			stringEntity.setContentType("application/x-www-form-urlencoded");
			httpPost.setEntity(stringEntity);
			// 执行发送，获取相应结果
			httpResponse = httpClient.execute(httpPost);
			httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity);
		} catch (Exception e) {
			log.error("请求http接口失败", e);
//			throw new ServiceException(406, "请求http接口失败");
		} finally {
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				log.error("HttpUtil.doPost finally EntityUtils.consume:", e);
			}
		}
		// 请求接口的响应时间
		endTime = System.currentTimeMillis();
		log.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
		return result;
	}

	/**
	 * 将Object对象里面的属性和值转化成Map对象
	 *
	 * @param obj
	 * @return
	 * @throws IllegalAccessException
	 */

	public Map<String, String> object2Map(Object obj) {
		Map<String, String> map = new HashMap<>();
		if (obj == null) {
			return map;
		}
		Class clazz = obj.getClass();
		Field[] fields = clazz.getDeclaredFields();
		try {
			for (Field field : fields) {
				field.setAccessible(true);
				map.put(field.getName(), (String) field.get(obj));
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return map;
	}

	public static String postFormDataMethod(String url, Map<String, String> params, String contentType,
			Map<String, String> header) {
		// 创建HttpClientBuilder
		HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
		// HttpClient
		CloseableHttpClient client = httpClientBuilder.build();
		client = (CloseableHttpClient) wrapClient(client);

		HttpPost post = new HttpPost(url);
		CloseableHttpResponse res = null;
		try {
			List<NameValuePair> list = new ArrayList<NameValuePair>();
			for (String key : params.keySet()) {
				list.add(new BasicNameValuePair(key, params.get(key)));
			}
			// url格式编码
			UrlEncodedFormEntity uefEntity = new UrlEncodedFormEntity(list, "UTF-8");
			post.setEntity(uefEntity);
			for (String key : header.keySet()) {
				post.addHeader(key, header.get(key));
			}

			res = client.execute(post);
			HttpEntity entity = res.getEntity();
			return EntityUtils.toString(entity, "utf-8");
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if(null != res){
				res.close();
				}
				client.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return "";
	}

	private static HttpClient wrapClient(HttpClient base) {
		try {
			SSLContext ctx = SSLContext.getInstance("TLSv1");
			X509TrustManager tm = new X509TrustManager() {
				public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
				}

				public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
				}

				public X509Certificate[] getAcceptedIssuers() {
					return null;
				}
			};
			ctx.init(null, new TrustManager[] { tm }, null);
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(ctx, new String[] { "TLSv1" }, null,
					SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
			CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
			return httpclient;

		} catch (Exception ex) {
			return null;
		}
	}

	// application/json格式请求
	public static String doHeaderPostFormData(String url, String jsonParam, Map<String, String> paramHeader,String contentType) {
		// 声明返回结果
		String result = "";
		// 开始请求API接口时间
		long startTime = System.currentTimeMillis();
		// 请求API接口的响应时间
		long endTime = 0L;
		HttpEntity httpEntity = null;
		HttpResponse httpResponse = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(5000).setConnectionRequestTimeout(5000)
				.setSocketTimeout(5000).build();
		try {
			// 设置请求头和报文
			HttpPost httpPost = new HttpPost(url);
			httpPost.setConfig(requestConfig);
			Header header = new BasicHeader("Accept-Encoding", "utf-8");
			for (String key : paramHeader.keySet()) {
				httpPost.setHeader(key, paramHeader.get(key));
			}
			if(StringUtils.isEmpty(contentType)){
				httpPost.setHeader("Content-Type", "application/json");
			}else if("formData".equals(contentType)){
				httpPost.setHeader("Content-Type", "multipart/form-data");
			}
			httpPost.setHeader(header);
			// 设置报文和通讯格式
			if (jsonParam != null) {
				StringEntity stringEntity = new StringEntity(jsonParam, "UTF-8");
				stringEntity.setContentEncoding("UTF-8");
				httpPost.setEntity(stringEntity);
			}

			// 执行发送，获取相应结果
			httpResponse = httpClient.execute(httpPost);
			httpEntity = httpResponse.getEntity();
			result = EntityUtils.toString(httpEntity);
		} catch (Exception e) {
			log.error("请求http接口失败", e);
//			throw new ServiceException(406, "请求http接口失败");

		} finally {
			try {
				EntityUtils.consume(httpEntity);
			} catch (IOException e) {
				log.error("HttpUtil.doPost finally EntityUtils.consume:", e);
			}
		}
		// 请求接口的响应时间
		endTime = System.currentTimeMillis();
		log.info("请求{}接口的响应报文内容为{},本次请求API接口的响应时间为:{}毫秒", url, result, (endTime - startTime));
		return result;
	}

	public static final byte[] input2byte(InputStream inStream)
            throws IOException {
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        byte[] buff = new byte[100];
        int rc = 0;
        while ((rc = inStream.read(buff, 0, 100)) > 0) {
            swapStream.write(buff, 0, rc);
        }
        byte[] in2b = swapStream.toByteArray();
        return in2b;
    }


}
